using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.WebTesting;

namespace HtmlTagInnerTextTests
{
    public static class AssertHelpers
    {
        public static void ThrowsException<T>(Action action) where T : Exception
        {
            try
            {
                action();

                Assert.Fail("Exception not thrown");

            }
            catch (T)
            {
            }
        }
        public static void ThrowsArgumentException<T>(Action action, string paramName) where T : ArgumentException
        {
            try
            {
                action();

                Assert.Fail("Exception not thrown");

            }
            catch (T exception)
            {
                Assert.AreEqual(paramName, exception.ParamName, "Argument Exception had different parameter name. Expected '{0}', actual '{1}'", paramName, exception.ParamName);
            }
        }

        public static void AssertCollectionsEqual<T>(ICollection<T> expected, ICollection<T> actual, Func<T,T,bool> comparer)
        {
            if (expected == null)
            {
                if (actual == null)
                {
                    return;
                }
                Assert.Fail("actual value is null");
                return;
            }
            Assert.AreEqual(expected.Count, actual.Count, "Collections are different sizes. Expected {0}, actual {1}", expected.Count, actual.Count);

            // TODO Get a LINQ Zip implementation to simplify this!
            IEnumerator<T> enumeratorExpected = expected.GetEnumerator();
            IEnumerator<T> enumeratorActual = actual.GetEnumerator();

            while (enumeratorExpected.MoveNext() && enumeratorActual.MoveNext())
            {
                T parameterExpected = enumeratorExpected.Current;
                T parameterActual = enumeratorActual.Current;

                
                Assert.IsTrue(comparer(parameterExpected, parameterActual)); 
            }
        }
        public static void AssertCollectionsEqual(ICollection<WebTestRequest> expected, ICollection<WebTestRequest> actual)
        {
            AssertCollectionsEqual(
                expected,
                actual,
                (e, a) =>
                    e.Url == a.Url
                );
        }
        public static void AssertCollectionsEqual(ICollection<QueryStringParameter> expected, ICollection<QueryStringParameter> actual)
        {
            AssertCollectionsEqual(
                expected,
                actual, 
                (e, a) =>
                    e.Name == a.Name
                    && e.Value == a.Value
                );
        }
        
    }
}